package com.mr.base.alpha.utils;

import com.mr.base.core.common.enums.CodeEnum;
import com.mr.base.core.common.exception.BaseException;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.ArrayConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.commons.beanutils.converters.StringConverter;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MRBeanUtils {

    private static BeanUtilsBean beanUtilsStatic;

    static{
        ConvertUtilsBean convertBean = new ConvertUtilsBean();

        final ArrayConverter longArrayConverter = new ArrayConverter(String[].class,new LongConverter());
        final ArrayConverter stringArrayConverter = new ArrayConverter(String[].class,new StringConverter());
        final ArrayConverter integerArrayConverter = new ArrayConverter(String[].class,new IntegerConverter());

        convertBean.register(new LongConverter() , Long.class);
        convertBean.register(stringArrayConverter , String[].class);
        convertBean.register(longArrayConverter , Long[].class);
        convertBean.register(integerArrayConverter , Integer[].class);

        BeanUtilsBean beanUtils = new BeanUtilsBean(convertBean);
        beanUtilsStatic = beanUtils;
    }

    public static <T> T copyProperties(Class<T> targetClass, Object source) {

        if (source == null) {
            return null;
        }


        T target = null;
        try {
            target = targetClass.newInstance();
            beanUtilsStatic.copyProperties( target , source);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return target;
    }

    public static class StringConvertArray implements Converter {

        @Override
        public <T> T convert(Class<T> type, Object value) {

            final Class<T> targetType  = ConvertUtils.primitiveToWrapper(type);

            if (value == null) {
                return targetType.cast(Collections.emptyList());
            }

            if (type.isInstance(value)) {
                return targetType.cast(value);
            }

            if (!String.class.isInstance(value)) {
                throw new BaseException(CodeEnum.USER_ERROR_A0400);
            }

            if (!targetType.isArray()) {
                throw new IllegalArgumentException("Default type must be an array.");
            }

            final String str = (String) value;
            final List<String> data = Arrays.asList(str.split(","));

            final Class<?> componentType = type.getComponentType();
            final Object newArray = Array.newInstance(componentType, data.size());

            for (int i = 0; i < data.size(); i++) {
                final String element = data.get(i);
                final Object componentElement = elementConverter(componentType, element);
                Array.set(newArray, i, componentElement);
            }

            return targetType.cast(newArray);
        }

        public Object elementConverter(Class<?> componentType , String element){

            final String typeName = componentType.toString();
            if (typeName.contains("String")) {
                return element;
            }else if(typeName.contains("Integer")){
                return Integer.parseInt(element);
            }else if(typeName.contains("Long")){
                return Long.parseLong(element);
            }

            return null;
        }

    }

}
